home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1994 / MacHack 1994.toast / MacHack™ 1987-1994 / MacHack™ '90 / MacHack'90 Proceedings / John Norstad / Reusable Code / Source / vol.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-06-10  |  20.7 KB  |  713 lines  |  [TEXT/MPS ]

  1. /*______________________________________________________________________
  2.  
  3.     vol.c - Volume Selection Module.
  4.     
  5.     Copyright © 1988, 1989, 1990 Northwestern University.  Permission is 
  6.     granted to use this code in your own projects, provided you give credit 
  7.     to both John Norstad and Northwestern University in your about box or 
  8.     document.
  9.     
  10.     This reusable module implements volume selection as in Apple's 
  11.     standard file package.
  12.     
  13.     The caller supplies a Drive button, an Eject button, and a rectangle
  14.     in which the name of the currently selected volume should be displayed.
  15.     
  16.     The module takes care of cycling through selected on-line volumes,
  17.     processing hits in the drive and eject buttons, properly hiliting
  18.     these buttons, processing disk insertion events, and drawing the 
  19.     volume name in response to update events.
  20.     
  21.     In addition to the volume name displayed in a rectangle, the caller 
  22.     can also request that small floppy and hard drive icons be displayed.  
  23.     The module displays the appropriate small icon in a caller-specified 
  24.     rectangle.  The caller supplies the small icons.
  25.     
  26.     If the current system supports popup menus, the volume name rectangle is
  27.     framed with a drop shadow.  If the user clicks in this rectangle a popup
  28.     menu is presented listing all mounted volumes.
  29.     
  30.     All of the routines do error checking, and return an error code
  31.     as their function result.
  32.     
  33.     This module should only be used in a modal environment (e.g., modal
  34.     dialogs).  The reason is that it assumes only it is mounting and
  35.     unmounting volumes.  In a non-modal environment this assumption
  36.     is invalid.
  37.     
  38.     All of the code placed in its own segment named "vol", except for the
  39.     vol_Init routine, which is placed in segment voli.
  40. _____________________________________________________________________*/
  41.  
  42.  
  43. #pragma load "precompile"
  44. #include "vol.h"
  45. #include "utl.h"
  46.  
  47. #pragma segment vol
  48.  
  49. /*______________________________________________________________________
  50.  
  51.     Global Variables.
  52. _____________________________________________________________________*/
  53.  
  54.  
  55. static ControlHandle    DriveH;        /* handle to drive push button */
  56. static ControlHandle    EjectH;        /* handle to eject push button */
  57. static Rect                *NameRect;    /* pointer to volume name rectangle */
  58. static Rect                AdjNameRect;    /* rectangle enclosing current vol name,
  59.                                                 adjusted for width of name */
  60. static Rect                *IconRect;    /* pointer to small vol icon rectangle */
  61. static Handle            FloppyH;        /*    handle to small floppy icon */
  62. static Handle            HardH;        /* handle to small hard drive icon */
  63. static Boolean            UnmountFlag;    /* true to unmount ejected volumes */
  64. static short            CurVol;        /* index of currently selected volume,
  65.                                                 or 0 if none */
  66. static short            ApplVol;        /* vol ref num of vol contng current appl */
  67. static short            SysVol;        /* vol ref num of system vol */
  68. static Boolean            HavePopUp;     /* true if system supports popup menus */
  69.  
  70. /*______________________________________________________________________
  71.  
  72.     NextVol - Advance to the Next Volume.
  73.     
  74.     Exit:        function result = error code.
  75. _____________________________________________________________________*/
  76.  
  77.  
  78. static OSErr NextVol(void)
  79.  
  80. {
  81.     HParamBlockRec    pBlock;                /* vol info param block */
  82.     OSErr                rCode;                /* result code */
  83.     short                volInx;                /* volume index */
  84.     
  85.     pBlock.volumeParam.ioNamePtr = nil;
  86.     volInx = CurVol;
  87.     while (true) {
  88.         pBlock.volumeParam.ioVolIndex = ++volInx;
  89.         pBlock.volumeParam.ioVRefNum = 0;
  90.         if (rCode = PBHGetVInfo(&pBlock, false)) {
  91.             volInx = 0;
  92.         } else if (pBlock.volumeParam.ioVDrvInfo) {
  93.             CurVol = volInx;
  94.             return noErr;
  95.         };
  96.         if (volInx == CurVol) {
  97.             CurVol = 0;
  98.             return noErr;
  99.         };
  100.     };
  101. }
  102.  
  103. /*______________________________________________________________________
  104.  
  105.     HiliteDrive() - Hilite the Drive Button.
  106.     
  107.     The drive button is hilited iff there are at least two on-line
  108.     volumes.
  109. _____________________________________________________________________*/
  110.  
  111.  
  112. static void HiliteDrive(void)
  113.  
  114. {
  115.     HParamBlockRec    pBlock;                /* vol info param block */
  116.     short                volInx;                /* vol index */
  117.     short                numOnLine;            /* number of online vols */
  118.     OSErr                rCode;                /* result code */
  119.     
  120.     pBlock.volumeParam.ioNamePtr = nil;
  121.     volInx = 0;
  122.     numOnLine = 0;
  123.     while (true) {
  124.         pBlock.volumeParam.ioVolIndex = ++volInx;
  125.         pBlock.volumeParam.ioVRefNum = 0;
  126.         if (rCode = PBHGetVInfo(&pBlock, false)) break;
  127.         if (pBlock.volumeParam.ioVDrvInfo) numOnLine++;
  128.         if (numOnLine > 1 ) {
  129.             HiliteControl(DriveH, 0);
  130.             return;
  131.         };
  132.     };
  133.     HiliteControl(DriveH, 255);
  134. }
  135.  
  136. /*______________________________________________________________________
  137.  
  138.     HiliteEject() - Hilite the eject Button.
  139.     
  140.     Exit:        function result = error code.
  141.     
  142.     The eject button is hilited iff the current volume is ejectable.
  143. _____________________________________________________________________*/
  144.  
  145.  
  146. static OSErr HiliteEject(void)
  147.  
  148. {
  149.     short                vRefNum;                /* vol ref num of cur vol */
  150.     OSErr                rCode;                /* result code */
  151.     
  152.     /* If there is no current volume unhilite the eject button. */
  153.     
  154.     if (!CurVol) {
  155.         HiliteControl(EjectH, 255);
  156.         return noErr;
  157.     };
  158.     
  159.     /* Hilite the button iff the cur vol is ejectable. */
  160.     
  161.     if (rCode = vol_GetSel(&vRefNum)) return rCode;
  162.     HiliteControl(EjectH, utl_Ejectable(vRefNum) ? 0 : 255);
  163.     return noErr;
  164. }
  165.  
  166. /*______________________________________________________________________
  167.  
  168.     Inval - Invalidate the volume name and icon rectangles.
  169. _____________________________________________________________________*/
  170.  
  171.  
  172. static void Inval(void)
  173.  
  174. {
  175.     Rect        boxRect;
  176.  
  177.     boxRect = *NameRect;
  178.     InsetRect(&boxRect, -2, -2);
  179.     InvalRect(&boxRect);
  180.     if (IconRect) InvalRect(IconRect);
  181. }
  182.  
  183. /*______________________________________________________________________
  184.  
  185.     vol_Init - Initialize.
  186.     
  187.     Entry:    driveH = handle to drive push button control.
  188.                 ejectH = handle to eject push button control.
  189.                 nameRect = pointer to volume name rectangle.
  190.                 iconRect = pointer to small volume icon rectangle, 
  191.                     or nil if none.
  192.                 floppyH = handle to small floppy icon, or nil if none.
  193.                 hardH = handle to small hard drive icon, or nil if none.
  194.                 applSel = true if the initial volume should be the volume
  195.                     containing the current application.  False if the initial
  196.                     volume should be some other volume (if there is one).
  197.                 unmmountFlag = true if ejected floppies should also be 
  198.                     unmounted.  The boot volume and the volume containing the 
  199.                     current application are never unmounted.
  200.                     
  201.     Exit:        function result = error code.
  202.                     
  203.     vol_Init must be called before calling any of the other routines
  204.     in the module.  It may be called more than once to reinitialize
  205.     the module.
  206.                     
  207.     vol_Init saves the parameters in private globals, selects an 
  208.     appropriate initial volume, and hilites the drive and eject buttons 
  209.     appropriately.
  210.     
  211.     Don't forget to do a SetPort to the window before calling this routine.
  212. _____________________________________________________________________*/
  213.  
  214.  
  215. #pragma segment voli
  216.  
  217. OSErr vol_Init (ControlHandle driveH, ControlHandle ejectH, 
  218.     Rect *nameRect, Rect *icnRect, Handle floppyH, 
  219.     Handle hardH, Boolean applSel, Boolean unmountFlag)
  220.     
  221. {
  222.  
  223.     HParamBlockRec    pBlock;                /* Vol info param block */
  224.     short                applInx;                /* index of application volume */
  225.     OSErr                rCode;                /* result code */
  226.     
  227.     /* Save parameter values in private global variables. */
  228.     
  229.     DriveH = driveH;
  230.     EjectH = ejectH;
  231.     NameRect = nameRect;
  232.     IconRect = icnRect;
  233.     FloppyH = floppyH;
  234.     HardH = hardH;
  235.     UnmountFlag = unmountFlag;
  236.     
  237.     /* Get applInx = index of volume containing current application,
  238.         and ApplVol = vol ref num of applicaton volume. */
  239.     
  240.     pBlock.volumeParam.ioNamePtr = nil;
  241.     ApplVol = utl_GetApplVol();
  242.     applInx = 0;
  243.     do {
  244.         pBlock.volumeParam.ioVolIndex = ++applInx;
  245.         pBlock.volumeParam.ioVRefNum = 0;
  246.         rCode = PBHGetVInfo(&pBlock, false);
  247.     } while (!rCode && pBlock.volumeParam.ioVRefNum != ApplVol);
  248.     if (rCode) return rCode;
  249.     
  250.     /* Select initial volume.  */
  251.     
  252.     if (applSel) {
  253.         CurVol = applInx;
  254.     } else {
  255.         CurVol = 0;
  256.         do {
  257.             pBlock.volumeParam.ioVolIndex = ++CurVol;
  258.             pBlock.volumeParam.ioVRefNum = 0;
  259.             rCode = PBHGetVInfo(&pBlock, false);
  260.         } while (!rCode && (!pBlock.volumeParam.ioVDrvInfo || 
  261.             pBlock.volumeParam.ioVRefNum == ApplVol));
  262.         if (rCode) CurVol = applInx;
  263.     };
  264.     
  265.     /* Get SysVol = vol ref num of system volume. */
  266.     
  267.     SysVol = utl_GetSysVol();
  268.     
  269.     /* Find out whether the system supports popup menus. */
  270.     
  271.     HavePopUp = utl_SysHasPopUp();
  272.         
  273.     /* Hilite buttons and invalidate rectangles. */
  274.     
  275.     HiliteDrive();
  276.     if (rCode = HiliteEject()) return rCode;
  277.     Inval();
  278.     return noErr;
  279. }
  280.  
  281. #pragma segment vol
  282.  
  283. /*______________________________________________________________________
  284.  
  285.     vol_DoDrive - Process Drive Button Hit.
  286.                     
  287.     Exit:        function result = error code.
  288.     
  289.     This routine must be called whenever there's a hit in the Drive
  290.     button.  It advances to the next on-line volume, hilites the 
  291.     eject button appropriately, and invalidates the volume name and 
  292.     icon rectangles.
  293.     
  294.     To perfectly mimic the standard file package, you can also call this
  295.     routine whenever the tab key is pressed.
  296.     
  297.     Don't forget to do a SetPort to the window before calling this routine.
  298. _____________________________________________________________________*/
  299.  
  300.  
  301. OSErr vol_DoDrive (void)
  302.  
  303. {
  304.     OSErr        rCode;            /* result code */
  305.  
  306.     if (rCode = NextVol()) return rCode;
  307.     if (rCode = HiliteEject()) return rCode;
  308.     Inval();
  309.     return noErr;
  310. }
  311.  
  312. /*______________________________________________________________________
  313.  
  314.     vol_DoPopUp - Present Volume Popup Menu.
  315.     
  316.     Entry:    where = location of mouse down, local coords.
  317.                 menuID = menu id to use for popup menu.
  318.                     
  319.     Exit:        function result = error code.
  320.     
  321.     This routine should be called whenever there's a mouse hit in the volume 
  322.     name rectangle.  It builds and presents a pop up menu listing all the 
  323.     mounted volumes.  The current volume is set to the volume selected from 
  324.     the menu by the user.
  325.     
  326.     The routine returns immediately if the mouse down event is not inside
  327.     the volume name rectangle.  It also returns immediately if the ROM or
  328.     system does not support popup menus.
  329.     
  330.     Don't forget to do a SetPort to the window before calling this routine.
  331. _____________________________________________________________________*/
  332.  
  333.  
  334. OSErr vol_DoPopUp (Point where, short menuID)
  335.  
  336. {
  337.     MenuHandle        theMenu;                /* handle to popup menu */
  338.     long                theItem;                /* 16/menu number, 16/item number */
  339.     short                volInx;                /* index in volume list */
  340.     HParamBlockRec    pBlock;                /* vol info param block */
  341.     Str255            volName;                /* vol name */
  342.     OSErr                rCode;                /* result code */
  343.     Point                whereMenu;            /* loc of popup menu, global coords */
  344.     short                item;                    /* menu item number */
  345.     short                checkedItem;        /* menu item number of checked item */
  346.     
  347.     /* Return if pop up menus are not available on this sytem. */
  348.     
  349.     if (!HavePopUp) return noErr;
  350.     
  351.     /* Return if mousedown not in volume name rectangle. */
  352.     
  353.     if (!PtInRect(where, &AdjNameRect)) return noErr;
  354.     
  355.     /* Return if there is no current volume. */
  356.     
  357.     if (!CurVol) return noErr;
  358.     
  359.     /* Create the menu. */
  360.     
  361.     theMenu = NewMenu(menuID, "\p");
  362.     
  363.     /* Fill the menu with the names of all currently mounted volumes.  Put
  364.         a check mark next to the currently selected volume. */
  365.     
  366.     volInx = item = 0;
  367.     pBlock.volumeParam.ioNamePtr = volName;
  368.     while (true) {
  369.         pBlock.volumeParam.ioVolIndex = ++volInx;
  370.         pBlock.volumeParam.ioVRefNum = 0;
  371.         rCode = PBHGetVInfo(&pBlock, false);
  372.         if (rCode) break;
  373.         if (pBlock.volumeParam.ioVDrvInfo) {
  374.             AppendMenu(theMenu, "\p ");
  375.             SetItem(theMenu, ++item, volName);
  376.             if (volInx == CurVol) 
  377.                 CheckItem(theMenu, checkedItem = item, true);
  378.         };
  379.     };
  380.         
  381.     /* Insert menu into menu bar. */
  382.     
  383.     InsertMenu(theMenu, -1);
  384.     
  385.     /* Pop it up.  Extract the item number selected.  Make the selected item
  386.         the current volume. */
  387.     
  388.     SetPt(&whereMenu, NameRect->left, NameRect->top);
  389.     LocalToGlobal(&whereMenu);
  390.     if (IconRect) InvertRect(IconRect);
  391.     theItem = PopUpMenuSelect(theMenu, whereMenu.v, whereMenu.h, 
  392.         checkedItem);
  393.     if (IconRect) InvertRect(IconRect);
  394.     if ((theItem >> 16) & 0xffff) {
  395.         item = theItem & 0xffff;
  396.         volInx = 0;
  397.         pBlock.volumeParam.ioNamePtr = nil;
  398.         while (true) {
  399.             pBlock.volumeParam.ioVolIndex = ++volInx;
  400.             pBlock.volumeParam.ioVRefNum = 0;
  401.             rCode = PBHGetVInfo(&pBlock, false);
  402.             if (rCode) break;
  403.             if (pBlock.volumeParam.ioVDrvInfo) {
  404.                 if (!(--item)) {
  405.                     CurVol = volInx;
  406.                     break;
  407.                 };
  408.             };
  409.         };
  410.         if (rCode = HiliteEject()) return rCode;
  411.         Inval();
  412.     };
  413.     
  414.     /* Delete and dispose of the menu and return. */
  415.     
  416.     DeleteMenu(menuID);
  417.     DisposeMenu(theMenu);
  418.     return noErr;
  419. }
  420.  
  421. /*______________________________________________________________________
  422.  
  423.     vol_DoEject - Process eject Button Hit.
  424.                     
  425.     Exit:        function result = error code.
  426.     
  427.     This routine must be called whenever there's a hit in the eject
  428.     button.  It ejects the currently selected volume, and unmounts it
  429.     if the unmount option was selected and the volume is not the
  430.     startup volume or the one containing the current application.  It 
  431.     then advances to the next on-line volume, hilites the Drive and 
  432.     eject buttons appropriately, and invalidates the volume name and 
  433.     icon rectangles.
  434.     
  435.     Don't forget to do a SetPort to the window before calling this routine.
  436. _____________________________________________________________________*/
  437.  
  438.  
  439. OSErr vol_DoEject (void)
  440.  
  441. {
  442.     HParamBlockRec    pBlock;                /* vol info param block */
  443.     OSErr                rCode;                /* result code */
  444.     short                volRefNum;            /* vol ref num of current vol */
  445.     
  446.     /* eject the current volume. */
  447.     
  448.     pBlock.volumeParam.ioNamePtr = nil;
  449.     pBlock.volumeParam.ioVolIndex = CurVol;
  450.     pBlock.volumeParam.ioVRefNum = 0;
  451.     if (rCode = PBHGetVInfo(&pBlock, false)) return rCode;
  452.     volRefNum = pBlock.volumeParam.ioVRefNum;
  453.     if (rCode = Eject(nil, volRefNum)) return rCode;
  454.     
  455.     /* If UnmountFlag is true, and the volume is not the system or
  456.         application volume, then unmount it. */
  457.         
  458.     if (UnmountFlag && volRefNum != SysVol && volRefNum != ApplVol) {
  459.         if (rCode = UnmountVol(nil, volRefNum)) return rCode;
  460.         CurVol = 0;
  461.     };
  462.     
  463.     /* Advance to next volume, hilite the buttons, and invalidate the 
  464.     rectangles. */
  465.         
  466.     if(rCode = NextVol()) return rCode;
  467.     HiliteDrive();
  468.     if (rCode = HiliteEject()) return rCode;
  469.     Inval();
  470.     return noErr;
  471. }
  472.  
  473. /*______________________________________________________________________
  474.  
  475.     vol_DoInsert - Process Disk Insertion Evect.
  476.     
  477.     Entry:    message = message field from event record.
  478.                     
  479.     Exit:        function result = error code.
  480.     
  481.     This routine must be called whenever there's a disk insertion event.
  482.     It makes the inserted volume the current volume, hilites the
  483.     Drive and eject buttons appropriately, and invalidates the volume
  484.     name and icon rectangles.
  485.     
  486.     Don't forget to do a SetPort to the window before calling this routine.
  487. _____________________________________________________________________*/
  488.  
  489.  
  490. OSErr vol_DoInsert (long message)
  491.  
  492. {
  493.     OSErr                rCode;                /* result code */
  494.     short                vRefNum;                /* vol ref num of inserted disk */
  495.  
  496.     /* Process the disk insertion event, and get the vol ref num */
  497.     
  498.     if (rCode = utl_DoDiskInsert(message, &vRefNum)) return rCode;
  499.     
  500.     /* Make the new disk the current volume. */
  501.     
  502.     if (rCode = vol_SetSel(vRefNum, true)) return rCode;
  503. }
  504.  
  505. /*______________________________________________________________________
  506.  
  507.     vol_DoUpdate - Process Update Event.
  508.                     
  509.     Exit:        function result = error code.
  510.     
  511.     This routine must be called whenever an update event occurs.  It
  512.     draws the volume name using the font attributes.  It also draws 
  513.     the proper small icon.
  514.     
  515.     If the current system supports popup menus, the volume name is also 
  516.     framed, with a drop shadow.
  517.     
  518.     Don't forget to do a SetPort to the window, call BeginUpdate, and
  519.     set your desired font and size before calling this routine.
  520. _____________________________________________________________________*/
  521.  
  522.  
  523. OSErr vol_DoUpdate (void)
  524.  
  525. {
  526.     HParamBlockRec    pBlock;                /* vol info param block */
  527.     Str255            volName;                /* vol name */
  528.     OSErr                rCode;                /* result code */
  529.     Rect                textRect;            /* rectangle for TextBox */
  530.     short                nameWidth;            /* width of vol name */
  531.     short                vRefNum;                /* vol ref num of cur vol */
  532.     short                slop;                    /* extra pixels needed in name width */
  533.     PolyHandle        triangle;            /* handle to triangle polygon */
  534.     
  535.     /* Return if there is no current volume. */
  536.     
  537.     if (!CurVol) return noErr;
  538.     
  539.     /* Get the volume name. */
  540.     
  541.     pBlock.volumeParam.ioNamePtr = volName;
  542.     pBlock.volumeParam.ioVolIndex = CurVol;
  543.     pBlock.volumeParam.ioVRefNum = 0;
  544.     if (rCode = PBHGetVInfo(&pBlock, false)) return rCode;
  545.     
  546.     /* If the name is too long truncate it and append the ellipsis char "…" */
  547.     
  548.     slop = HavePopUp ? 20 : 9;
  549.     while (true) {
  550.         nameWidth = StringWidth(volName);
  551.         if (NameRect->left + nameWidth + slop <= NameRect->right) break;
  552.         (*volName)--;
  553.         *(volName + *volName) = '…';
  554.     };
  555.  
  556.     /* Draw the volume name and icon. */
  557.     
  558.     textRect = *NameRect;
  559.     textRect.left += 4;
  560.     TextBox(volName+1, *volName, &textRect, teJustLeft);
  561.     if (IconRect) {
  562.         if (rCode = vol_GetSel(&vRefNum)) return rCode;
  563.         utl_PlotSmallIcon (IconRect, utl_Ejectable(vRefNum) ? FloppyH : HardH);
  564.     };
  565.         
  566.     /* Frame the volume name, with a drop shadow, and draw the triangle. */
  567.         
  568.     if (HavePopUp) {
  569.         AdjNameRect = *NameRect;
  570.         AdjNameRect.right = AdjNameRect.left + nameWidth + slop;
  571.         InsetRect(&AdjNameRect, -1, -1);
  572.         FrameRect(&AdjNameRect);
  573.         MoveTo(AdjNameRect.right, AdjNameRect.top+2);
  574.         LineTo(AdjNameRect.right, AdjNameRect.bottom);
  575.         LineTo(AdjNameRect.left+2, AdjNameRect.bottom);
  576.         triangle = OpenPoly();
  577.         MoveTo(AdjNameRect.right - 14, 
  578.             (AdjNameRect.top + AdjNameRect.bottom - 5)>>1);
  579.         Line(10, 0);
  580.         Line(-5, 5);
  581.         Line(-5, -5);
  582.         ClosePoly();
  583.         PaintPoly(triangle);
  584.         KillPoly(triangle);
  585.     };
  586.     return noErr;
  587. }
  588.  
  589. /*______________________________________________________________________
  590.  
  591.     vol_Verify - Verify and Adjust Selected Volume.
  592.     
  593.     Exit:        function result = error code.
  594.     
  595.     This routine should be called after any call to the standard file
  596.     package or any other activity which might have caused the volume
  597.     list to change state. 
  598.     
  599.     vol_Verify checks to make sure that the current volume still exists and 
  600.     is online.  If it isn't, it finds some other volume that is and makes it 
  601.     the current one.  
  602.  
  603.     The volume name and icon rectangles are invalidated, and the Drive and 
  604.     eject buttons are rehilited appropriately.
  605.     _____________________________________________________________________*/
  606.  
  607.  
  608. OSErr vol_Verify (void)
  609.  
  610. {
  611.     HParamBlockRec    pBlock;            /* vol info param block */
  612.     OSErr                rCode;            /* reslut code */
  613.     
  614.     if (!CurVol) {
  615.         rCode = NextVol();
  616.     } else {
  617.         pBlock.volumeParam.ioNamePtr = nil;
  618.         pBlock.volumeParam.ioVolIndex = CurVol;
  619.         pBlock.volumeParam.ioVRefNum = 0;
  620.         rCode = PBHGetVInfo(&pBlock, false);
  621.         if ((rCode == nsvErr) || !pBlock.volumeParam.ioVDrvInfo) {
  622.             CurVol = 0;
  623.             rCode = NextVol();
  624.         };
  625.     };
  626.     if (rCode) return rCode;
  627.     HiliteDrive();
  628.     if (rCode = HiliteEject()) return rCode;
  629.     Inval();
  630. }
  631.  
  632. /*______________________________________________________________________
  633.  
  634.     vol_GetSel - Get Volume Reference Number of Selected Volume.
  635.     
  636.     Exit:        *vRefNum = volume reference number.
  637.                 function result = error code (= nsvErr if no current vol).
  638. _____________________________________________________________________*/
  639.  
  640.  
  641. OSErr vol_GetSel (short *vRefNum)
  642.  
  643. {
  644.     HParamBlockRec    pBlock;                /* vol info param block */
  645.     OSErr                rCode;                /* result code */
  646.     
  647.     if (!CurVol) return nsvErr;
  648.     pBlock.volumeParam.ioNamePtr = nil;
  649.     pBlock.volumeParam.ioVolIndex = CurVol;
  650.     pBlock.volumeParam.ioVRefNum = 0;
  651.     if (rCode = PBHGetVInfo(&pBlock, false)) return rCode;
  652.     *vRefNum = pBlock.volumeParam.ioVRefNum;
  653.     return noErr;
  654. }
  655.  
  656. /*______________________________________________________________________
  657.  
  658.     vol_SetSel - Set Volume Reference Number of Selected Volume.
  659.     
  660.     Entry:    vRefNum = volume reference number.
  661.                 doButtons = true to hilite Drive and eject buttons.
  662.     
  663.     Exit:        function result = error code.
  664. _____________________________________________________________________*/
  665.  
  666.  
  667. OSErr vol_SetSel (short vRefNum, Boolean doButtons)
  668.  
  669. {
  670.     HParamBlockRec    pBlock;                /* vol info param block */
  671.     OSErr                rCode;                /* result code */
  672.     
  673.     CurVol = 0;
  674.     pBlock.volumeParam.ioNamePtr = nil;
  675.     do {
  676.         pBlock.volumeParam.ioVolIndex = ++CurVol;
  677.         pBlock.volumeParam.ioVRefNum = 0;
  678.         rCode = PBHGetVInfo(&pBlock, false);
  679.     } while (!rCode && pBlock.volumeParam.ioVRefNum != vRefNum);
  680.     if (rCode) return rCode;
  681.     if (doButtons) {
  682.         HiliteDrive();
  683.         if (rCode = HiliteEject()) return rCode;
  684.     };
  685.     Inval();
  686.     return noErr;
  687. }
  688.  
  689. /*______________________________________________________________________
  690.  
  691.     vol_GetName - Get Name of Selected Volume.
  692.     
  693.     Exit:        vName = volume name.
  694.                 function result = error code (= nsvErr if no current vol).
  695. _____________________________________________________________________*/
  696.  
  697.  
  698. OSErr vol_GetName (Str255 vName)
  699.  
  700. {
  701.     HParamBlockRec    pBlock;                /* vol info param block */
  702.     OSErr                rCode;                /* result code */
  703.     
  704.     if (!CurVol) return nsvErr;
  705.     
  706.     /* Get the volume name. */
  707.     
  708.     pBlock.volumeParam.ioNamePtr = vName;
  709.     pBlock.volumeParam.ioVolIndex = CurVol;
  710.     pBlock.volumeParam.ioVRefNum = 0;
  711.     if (rCode = PBHGetVInfo(&pBlock, false)) return rCode;
  712.     return noErr;
  713. }